<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Painting in Ruby Qt</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, painting, Qt, Ruby">
<meta name="description" content="This part of the Ruby Qt tutorial covers painting.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Painting</h1>

<p>
In this part of the Ruby Qt programming tutorial we will do some painting. 
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 

<p>
When do we need to paint? There are situations, when we need to create a 
widget from scratch. In such a case, we need to do painting. Or we want 
to create charts, special ornaments, effects or widget enhancements.  
</p>

<p>
The <code>Painter</code> class is instrumental when we do some 
painting in the Qt library. Paint events are received in the 
<code>paintEvent</code> method. To do custom painting, we must reimplement
this method. 
</p>


<h2>Patterns</h2>

<p>
In Qt, there are various patterns, that we can use to fill the interiors of shapes. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws nine rectangles.
# The interiors are filled with
# different built-in patterns.
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp &lt; Qt::Widget

    def initialize
        super
        
        setWindowTitle "Patterns"
        
        resize 350, 280
        move 300, 300

        show
    end
    
    
    def paintEvent event

        painter = Qt::Painter.new self
        
        drawPatterns painter
        painter.end
    end

    
    def drawPatterns painter

        painter.setPen Qt::NoPen

        painter.setBrush Qt::HorPattern
        painter.drawRect 10, 15, 90, 60

        painter.setBrush Qt::VerPattern
        painter.drawRect 130, 15, 90, 60

        painter.setBrush Qt::CrossPattern
        painter.drawRect 250, 15, 90, 60

        painter.setBrush Qt::Dense7Pattern
        painter.drawRect 10, 105, 90, 60

        painter.setBrush Qt::Dense6Pattern
        painter.drawRect 130, 105, 90, 60

        painter.setBrush Qt::Dense5Pattern
        painter.drawRect 250, 105, 90, 60

        painter.setBrush Qt::BDiagPattern
        painter.drawRect 10, 195, 90, 60

        painter.setBrush Qt::FDiagPattern
        painter.drawRect 130, 195, 90, 60

        painter.setBrush Qt::DiagCrossPattern
        painter.drawRect 250, 195, 90, 60
    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec
</pre>

<p>
In the code example, we will draw nine rectangles and fill them with
different brush patterns. 
</p>


<pre class="explanation">
def paintEvent event

    painter = Qt::Painter.new self

    drawPatterns painter
    painter.end
end
</pre>

<p>
When the window area needs to be redrawn, the <code>paintEvent</code> method
is called. This happens, when we resize the window, maximize it or minimize it etc. 
Inside this method, we create the <code>Painter</code> object. This object is used
to do all painting in Qt. The painting itself is delegated to the <code>drawPatterns</code> method.
</p>

<pre class="explanation">
painter.setPen Qt::NoPen
</pre>

<p>
The pen object is used to draw outlines of the shapes. In our example
we will not use a pen. 
</p>

<pre class="explanation">
painter.setBrush Qt::HorPattern
</pre>

<p>
We set a horizontal pattern as a brush. 
</p>

<pre class="explanation">
painter.drawRect 10, 15, 90, 60
</pre>

<p>
We draw a rectangle, with the current pen and brush.
The first two parameters of the method are the x, y coordinates.
The last two parameters are the width and height of the rectangle. 
</p>

<pre class="explanation">
painter.end
</pre>

<p>
Ends painting. Any resources used while painting are released. 
</p>

<img src="/img/gui/qtruby/patterns.png" alt="Patterns">
<div class="figure">Figure: Patterns</div>



<h2>Shapes</h2>

<p>
The Qt painting API can draw various shapes. The following programming code 
example will show some of them. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws basic shapes
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super
        
        setWindowTitle "Basic shapes"
        
        resize 350, 280
        move 300, 300

        show
    end
    
    
    def paintEvent event

          painter = Qt::Painter.new self
        
          drawShapes painter
          painter.end
    end

    
    def drawShapes painter

        painter.setRenderHint Qt::Painter::Antialiasing
        painter.setPen Qt::Color.new 150, 150, 150
        painter.setBrush Qt::Brush.new Qt::Color.new 150, 150, 150

        path1 = Qt::PainterPath.new

        path1.moveTo 5, 5
        path1.cubicTo 40, 5,  50, 50,  99, 99
        path1.cubicTo 5, 99,  50, 50,  5, 5
        painter.drawPath path1

        painter.drawPie 130, 20, 90, 60, 30*16, 120*16
        painter.drawChord 240, 30, 90, 60, 0, 16*180
        painter.drawRoundRect 20, 120, 80, 50

        points = []
        points.push  Qt::Point.new 130, 140
        points.push  Qt::Point.new 180, 170
        points.push  Qt::Point.new 180, 140
        points.push  Qt::Point.new 220, 110
        points.push  Qt::Point.new 140, 100

        polygon = Qt::Polygon.new points

        painter.drawPolygon polygon
        painter.drawRect 250, 110, 60, 60

        baseline = Qt::PointF.new 20, 250
        font = Qt::Font.new "Georgia", 55
        path2 = Qt::PainterPath.new
        path2.addText baseline, font, "Q"
        painter.drawPath path2

        painter.drawEllipse 140, 200, 60, 60
        painter.drawEllipse 240, 200, 90, 60

    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec
</pre>

<p>
In this code example, we draw nine different shapes on the window. A complex path, 
a pie, a chord, a rounded rectangle, a polygon, a rectangle, a character based shape,
a circle and an ellipse. 
</p>


<pre class="explanation">
painter.setRenderHint Qt::Painter::Antialiasing
</pre>

<p>
We use antialiasing in the example. Antialiased shapes look better, but it takes more 
time to draw them. 
</p>

<pre class="explanation">
painter.setPen Qt::Color.new 150, 150, 150
painter.setBrush Qt::Brush.new Qt::Color.new 150, 150, 150
</pre>

<p>
We use a dark gray pen and brush to draw the shapes. 
</p>

<pre class="explanation">
path1 = Qt::PainterPath.new

path1.moveTo 5, 5
path1.cubicTo 40, 5,  50, 50,  99, 99
path1.cubicTo 5, 99,  50, 50,  5, 5
painter.drawPath path1
</pre>

<p>
The first complex shape is created with the <code>PainterPath</code> object. 
The PainterPath class provides a container for painting operations. A painter path is an 
object composed of a number of graphical building blocks, such as rectangles, ellipses, lines, and curves.
</p>

<pre class="explanation">
painter.drawPie 130, 20, 90, 60, 30*16, 120*16
painter.drawChord 240, 30, 90, 60, 0, 16*180
painter.drawRoundRect 20, 120, 80, 50
</pre>

<p>
These three lines draw a pie, a chord and a rounded rectangle. 
</p>

<pre class="explanation">
points = []
points.push  Qt::Point.new 130, 140
points.push  Qt::Point.new 180, 170
points.push  Qt::Point.new 180, 140
points.push  Qt::Point.new 220, 110
points.push  Qt::Point.new 140, 100

polygon = Qt::Polygon.new points

painter.drawPolygon polygon
</pre>

<p>
We use an array of five points to create a polygon. 
</p>

<pre class="explanation">
baseline = Qt::PointF.new 20, 250
font = Qt::Font.new "Georgia", 55
path2 = Qt::PainterPath.new
path2.addText baseline, font, "Q"
painter.drawPath path2
</pre>

<p>
These lines create a character based shape. 
</p>

<pre class="explanation">
 painter.drawEllipse 140, 200, 60, 60
 painter.drawEllipse 240, 200, 90, 60
</pre>

<p>
These two lines create a circle and an ellipse respectively.
</p>

<img src="/img/gui/qtruby/shapes.png" alt="Shapes">
<div class="figure">Figure: Shapes</div>



<h2>Transparent rectangles</h2>

<p>
Transparency is the quality of being able to see through a material.
The easiest way to understand transparency is to imagine a piece of
glass or water. Technically, the rays of light can go through the 
glass and this way we can see objects behind the glass.
</p>

<p>
In computer graphics, we can achieve transparency effects using alpha compositing.
 Alpha compositing is the process of combining an image with a background 
to create the appearance of partial transparency. 
The composition process uses an alpha channel. (wikipedia.org, answers.com) 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws ten
# rectangles with different
# levels of transparency.
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp &lt; Qt::Widget

    def initialize
        super
        
        setWindowTitle "Transparent rectangles"
        
        resize 590, 90
        move 300, 300

        show
    end
    
    
    def paintEvent event

          painter = Qt::Painter.new self
        
          drawRectangles painter
          painter.end
    end

    
    def drawRectangles painter

        painter.setPen Qt::NoPen

        for i in 1..10
            painter.setBrush Qt::Brush.new Qt::Color.new 0, 0, 255, i*25
            painter.drawRect 50*i, 20, 40, 40
        end

    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec
</pre>

<p>
In the example we will draw ten rectangles with different levels of transparency. 
</p>

<pre class="explanation">
 painter.setPen Qt::NoPen
</pre>

<p>
We use no pen. 
</p>

<pre class="explanation">
for i in 1..10
    painter.setBrush Qt::Brush.new Qt::Color.new 0, 0, 255, i*25
    painter.drawRect 50*i, 20, 40, 40
end
</pre>

<p>
The last parameter of the Color object is the alpha transparency value. 
</p>


<img src="/img/gui/qtruby/trect.png" alt="Transparent rectangles">
<div class="figure">Figure: Transparent rectangles</div>


<h2>Donut Shape</h2>

<p>
In the following example we create a complex shape by rotating a bunch of ellipses. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws a donut
# shape
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super
        
        setWindowTitle "Donut"
        
        resize 350, 280
        move 300, 300

        show
    end
    
    
    def paintEvent event

          painter = Qt::Painter.new self
        
          drawDonut painter
          painter.end
    end

    
    def drawDonut painter

        painter.setRenderHint Qt::Painter::Antialiasing

        color = Qt::Color.new
        color.setNamedColor "#333333"

        pen = Qt::Pen.new color
        pen.setWidth 1
        painter.setPen pen

        w = width
        h = height

        painter.translate Qt::Point.new w/2, h/2

        72.times do
            painter.drawEllipse -125, -40, 250, 80
            painter.rotate 5.0
        end
    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec
</pre>

<p>
In this example, we create a donut. The shape resembles a cookie, hence the name donut. 
</p>


<pre class="explanation">
color = Qt::Color.new
color.setNamedColor "#333333"
</pre>

<p>
We can use a hexadecimal notation to create a color object. 
</p>

<pre class="explanation">
w = width
h = height
</pre>

<p>
Here we determine the width and height of the window. 
</p>

<pre class="explanation">
painter.translate Qt::Point.new w/2, h/2
</pre>

<p>
We move the coordinate system to the middle of the window. This way we
make the drawing mathematically easier. 
</p>

<pre class="explanation">
72.times do
    painter.drawEllipse -125, -40, 250, 80
    painter.rotate 5.0
end
</pre>

<p>
We draw an ellipse object 72 times. Each time, we rotate the
ellipse by 5 degrees. This will create our donut shape.
</p>


<img src="/img/gui/qtruby/donut.png" alt="Donut">
<div class="figure">Figure: Donut</div>


<h2>Drawing text</h2>

<p>
In the last example, we are going to draw text
on the window. 
</p>

<pre class="code">
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws text
# on the window
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super
        
        setWindowTitle "Soulmate"
        
        resize 370, 240
        move 300, 300

        show
    end
    
    
    def paintEvent event

          painter = Qt::Painter.new self
        
          drawText painter
          painter.end
    end

    
    def drawText painter

        painter.setBrush Qt::Brush.new Qt::Color.new 25, 25, 25
        painter.setFont Qt::Font.new "Purisa", 10

        painter.drawText Qt::Point.new(20, 30),
                "Most relationships seem so transitory"
        painter.drawText Qt::Point.new(20, 60),
                "They're good but not the permanent one"
        painter.drawText Qt::Point.new(20, 120),
                "Who doesn't long for someone to hold"
        painter.drawText Qt::Point.new(20, 150),
                "Who knows how to love without being told"
        painter.drawText Qt::Point.new(20, 180),
                "Somebody tell me why I'm on my own"
        painter.drawText Qt::Point.new(20, 210),
                "If there's a soulmate for everyone"

    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec
</pre>

<p>
We draw a song lyrics on the window. 
</p>

<pre class="explanation">
painter.setFont Qt::Font.new "Purisa", 10
</pre>

<p>
We set a Purisa font for our text. 
</p>

<pre class="explanation">
painter.drawText Qt::Point.new(20, 30),
        "Most relationships seem so transitory"
</pre>

<p>
The <code>drawText</code> method is used
to draw the text. 
</p>


<img src="/img/gui/qtruby/soulmate.png" alt="Drawing text">
<div class="figure">Figure: Drawing text</div>


<p>
In this part of the Ruby Qt programming tutorial, we did some
painting.
</p>

<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified July 6, 2009  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>


